package com.zhou.common.lib.util;

import com.zhou.common.lib.model.CommonPage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * JAVA对象属性拷贝工具类
 **/
@Slf4j
public final class BeanUtil {

    /**
     * 拷贝对象
     **/
    public static <T> T copyObject(Object src, Class<T> destClass) {
        if (src == null) {
            return null;
        }
        try {
            T destObj = destClass.newInstance();
            BeanUtils.copyProperties(src, destObj);
            return destObj;
        } catch (Exception e) {
            log.error("convertObject ERROR", e);
            return null;
        }
    }


    /**
     * 拷贝分页对象
     **/
    public static <T> CommonPage<T> copyPage(CommonPage src, Class<T> destClass) {
        if (src == null) {
            return null;
        }
        try {
            List list = src.getList();
            Long totalCount = src.getTotalCount();
            Long totalPage = src.getTotalPage();
            CommonPage<T> commonPage = new CommonPage<>();
            List<T> ts = BeanUtil.copyList(list, destClass);
            commonPage.setList(ts);
            commonPage.setTotalPage(totalPage);
            commonPage.setTotalCount(totalCount);
            return commonPage;
        } catch (Exception e) {
            log.error("convertObject ERROR", e);
            return null;
        }
    }

    /**
     * 拷贝列表List
     **/
    @SuppressWarnings("rawtypes")
    public static <T> List<T> copyList(List srcList, Class<T> destClass) {
        if (srcList == null) {
            return null;
        }
        if (srcList.size() == 0) {
            return new ArrayList<T>(1);
        }
        try {
            List<T> destList = new ArrayList<T>(srcList.size() + 10);
            for (int i = 0; i < srcList.size(); i++) {
                Object srcObj = srcList.get(i);
                T destObj = destClass.newInstance();
                BeanUtils.copyProperties(srcObj, destObj);
                destList.add(destObj);
            }
            return destList;
        } catch (Exception e) {
            log.error("copyList ERROR", e);
            return null;
        }
    }


    /**
     * 拷贝集合Set
     **/
    @SuppressWarnings("rawtypes")
    public static <T> Set<T> copySet(Set srcSet, Class<T> destClass) {
        if (srcSet == null) {
            return null;
        }
        if (srcSet.size() == 0) {
            return new HashSet<T>();
        }
        try {
            HashSet<T> destSet = new HashSet<T>((srcSet.size() + 1) * 2);
            Iterator iterator = srcSet.iterator();
            while (iterator.hasNext()) {
                Object srcObj = iterator.next();
                T destObj = destClass.newInstance();
                BeanUtils.copyProperties(srcObj, destObj);
                destSet.add(destObj);
            }
            return destSet;
        } catch (Exception e) {
            log.error("copySet ERROR", e);
            return null;
        }
    }

    /**
     * 拷贝属性（不拷贝  8种基本数据类型、NULL值；）
     **/
    public static void copyPropertiesWithoutNullValue(Object src, Object dest) {
        if (src == null || dest == null) {
            return;
        }

        Field[] fieldsOfSrc = src.getClass().getDeclaredFields();
        for (Field field : fieldsOfSrc) {
            field.setAccessible(true);
            String fieldName = field.getName();
            //不需要复制的情况A
            if ("serialVersionUID".equals(fieldName)) {
                continue;//参数名称: 系统保留的
            }

            Field fieldOfDest = null;
            try {
                fieldOfDest = dest.getClass().getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
            } catch (SecurityException e) {
            }
            //不需要复制的情况B
            if (fieldOfDest == null) {
                continue;//目标对象：没有同名属性
            }
            fieldOfDest.setAccessible(true);

            //不需要复制的情况C
            Class<?> fieldTypeOfSrc = field.getType();//源属性类型
            if (fieldTypeOfSrc.isPrimitive() || fieldTypeOfSrc.isSynthetic()) {
                continue; //不复制基本数据类型 和 组合类型
            }
            //不需要复制的情况D
            Class<?> fieldTypeOfDest = fieldOfDest.getType();//目标属性类型
            if (!fieldTypeOfSrc.equals(fieldTypeOfDest)) {
                continue;//目标对象：有同名属性，但类型不一样
            }

            try {
                //不需要复制的情况E
                Object value = field.get(src);
                if (value == null) {
                    continue;//值为NULL时
                }
                fieldOfDest.set(dest, value);
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            }
        }
    }

}



